#include "RgCSDAScorer.hh"

#include "G4Alpha.hh"
#include "G4Step.hh"
#include "G4Track.hh"
#include "G4UnitsTable.hh"
#include "MyMacros.hh"
//#include "G4SystemOfUnits.hh"
// #include "G4ParticleDefinition.hh"

RgCSDAScorer::RgCSDAScorer(G4String name, G4int depth, G4int weight) : G4VPrimitiveScorer(name, depth), fDepth(depth), fWeight(weight)
{
    _fAlpha = G4Alpha::Alpha();
}

G4bool RgCSDAScorer::ProcessHits(G4Step* step, G4TouchableHistory*)
{
    auto* const track = step->GetTrack();
    auto* const partDef = track->GetParticleDefinition();

    // ---- 1. 过滤：只记录主粒子，且只记录 α（可改成任何粒子） ----
    if (track->GetParentID() != 0) return true;  // 只盯 primary
    if (partDef != _fAlpha) return true;

    const G4int tkID = track->GetTrackID();
    // 第一次见这条 track 就新开一个 slot
    if (tkID >= (G4int)_fPerTrack.size()) _fPerTrack.resize(tkID + 1);

    TrackData& d = _fPerTrack[tkID];

    // ---- 3. 每一步累加 CSDA ----
    const auto stepLen = step->GetStepLength() / CLHEP::mm;
    d.csda += stepLen;
    //DINFOLN("````````````````````````````[RgCSDA/ProcessHits] stepLen {}", stepLen);

    // ---- 4. 粒子停掉或离开世界体积 → 写结果 ----
    G4bool stopped = (track->GetTrackStatus() == fStopAndKill) || (track->GetNextVolume() == nullptr);

    if (stopped)
    {
        d.end = track->GetPosition();

        // 5. 填 hits map（index=0 代表“整个 mesh 的唯一 bin”）
        G4int idx = 0;
        _fCSDAMap->add(idx, d.csda);
    }
    return true;
}

// ----------- 以下 boilerplate 直接抄即可 -----------
void RgCSDAScorer::Initialize(G4HCofThisEvent* HCE)
{
    //auto* const dctt = this->GetMultiFunctionalDetector();
    const auto& dcttName = this->GetMultiFunctionalDetector()->GetName();
    const auto& primName = this->GetName();
    // detector name, collection name

    _fCSDAMap = new G4THitsMap<G4double>(dcttName, primName);

    if (_fHCID[0] < 0)
    {
        _fHCID[0] = GetCollectionID(0);
    }
    HCE->AddHitsCollection(_fHCID[0], _fCSDAMap);
}

void RgCSDAScorer::EndOfEvent(G4HCofThisEvent*)
{  //
    /* 合并已在 add() 时完成，无需额外动作 */
}

void RgCSDAScorer::PrintAll()
{
    auto print = [](G4THitsMap<G4double>* m, G4String title)
    {
        G4cout << "-------- " << title << " --------" << G4endl;
        std::map<G4int, G4double*>::iterator it;
        for (it = m->GetMap()->begin(); it != m->GetMap()->end(); ++it)
            G4cout << " idx=" << it->first << "  val=" << G4BestUnit(*(it->second), "Length") << G4endl;
    };
    print(_fCSDAMap, "CSDA Range");
}